extends CharacterBody3D

@export var unit_name: String = "Basic Unit"
@export var max_health: float = 100.0
@export var attack_damage: float = 20.0
@export var attack_speed: float = 1.0
@export var movement_speed: float = 5.0
@export var attack_range: float = 3.0
@export var tier: int = 1
@export var cost: int = 1
@export var unit_class: String = "Fighter"
@export var ability: Ability = null

var current_health: float
var current_mana: float = 0.0
var max_mana: float = 100.0
var mana_per_attack: float = 10.0
var grid_position: Vector2i
var target_unit: Node3D = null
var is_player_unit: bool = true
var is_moving: bool = false
var target_position: Vector3
var attack_timer: float = 0.0
var is_in_combat: bool = false
var is_stunned: bool = false
var stun_duration: float = 0.0

# Base stats for synergy reset
var base_max_health: float
var base_attack_damage: float
var base_attack_speed: float
var base_movement_speed: float

# Bonus stats from synergies
var bonus_armor: float = 0.0
var bonus_attack_damage: float = 0.0
var bonus_attack_speed: float = 0.0
var bonus_ability_power: float = 0.0
var crit_chance: float = 0.0

signal unit_died(unit)
signal health_changed(current, maximum)
signal attack_performed(target)
signal ability_used(ability_name)

func _ready():
	current_health = max_health
	add_to_group("units")
	set_physics_process(false)
	
	# Store base stats
	base_max_health = max_health
	base_attack_damage = attack_damage
	base_attack_speed = attack_speed
	base_movement_speed = movement_speed
	
	# Add health bar
	var health_bar = preload("res://scripts/HealthBar3D.gd").new()
	add_child(health_bar)
	health_bar.setup(self)
	
	# Connect to VFX manager if available
	var vfx_manager = get_node_or_null("/root/Main/VFXManager")
	if vfx_manager:
		attack_performed.connect(func(target): 
			vfx_manager.spawn_hit_effect(target.global_position, Color(1.0, 0.5, 0.0))
		)
		ability_used.connect(func(ability_name): 
			vfx_manager.spawn_ability_effect(ability_name, global_position)
		)
	
func _physics_process(delta):
	if not is_in_combat:
		return
	
	# Update stun
	if is_stunned:
		stun_duration -= delta
		if stun_duration <= 0:
			is_stunned = false
		return
	
	# Update ability cooldown
	if ability:
		ability.update_cooldown(delta)
		
	if target_unit and is_instance_valid(target_unit):
		if is_in_range(target_unit):
			is_moving = false
			perform_attack(delta)
		else:
			move_toward_target(delta)
	else:
		find_new_target()

func move_toward_target(delta):
	if not target_unit:
		return
		
	var direction = (target_unit.global_position - global_position).normalized()
	direction.y = 0
	
	if direction.length() > 0:
		velocity = direction * movement_speed
		move_and_slide()
		
		look_at(global_position + direction, Vector3.UP)

func perform_attack(delta):
	attack_timer += delta
	var actual_attack_speed = attack_speed + bonus_attack_speed
	if attack_timer >= 1.0 / actual_attack_speed:
		attack_timer = 0.0
		if target_unit and target_unit.has_method("take_damage"):
			var damage = attack_damage + bonus_attack_damage
			
			# Check for critical strike
			if randf() * 100 < crit_chance:
				damage *= 2.0
				
			target_unit.take_damage(damage)
			emit_signal("attack_performed", target_unit)
			
			# Generate mana
			current_mana = min(current_mana + mana_per_attack, max_mana)
			
			# Try to use ability
			if ability and current_mana >= ability.mana_cost:
				if ability.use_ability(self, [target_unit]):
					current_mana -= ability.mana_cost
					emit_signal("ability_used", ability.ability_name)

func start_combat():
	is_in_combat = true
	set_physics_process(true)
	find_new_target()

func stop_combat():
	is_in_combat = false
	set_physics_process(false)
	target_unit = null
	is_moving = false

func find_new_target():
	target_unit = get_nearest_enemy()
	if target_unit:
		is_moving = true
	
func initialize(grid_x: int, grid_z: int, is_player: bool):
	grid_position = Vector2i(grid_x, grid_z)
	is_player_unit = is_player
	
	if is_player:
		add_to_group("player_units")
	else:
		add_to_group("enemy_units")

func take_damage(amount: float):
	current_health -= amount
	emit_signal("health_changed", current_health, max_health)
	
	# Spawn damage number
	var vfx_manager = get_node_or_null("/root/Main/VFXManager")
	if vfx_manager:
		vfx_manager.spawn_damage_number(global_position, amount, false, false)
	
	# Damage shake animation
	var ui_animator = get_node_or_null("/root/Main/UIAnimator")
	if ui_animator:
		ui_animator.animate_damage_shake(self)
	
	if current_health <= 0:
		die()

func die():
	emit_signal("unit_died", self)
	queue_free()

func get_nearest_enemy() -> Node3D:
	var enemy_group = "enemy_units" if is_player_unit else "player_units"
	var enemies = get_tree().get_nodes_in_group(enemy_group)
	
	if enemies.is_empty():
		return null
	
	var nearest = null
	var min_distance = INF
	
	for enemy in enemies:
		var distance = global_position.distance_to(enemy.global_position)
		if distance < min_distance:
			min_distance = distance
			nearest = enemy
	
	return nearest

func is_in_range(target: Node3D) -> bool:
	if not target:
		return false
	return global_position.distance_to(target.global_position) <= attack_range

# Synergy system methods
func get_unit_class() -> String:
	return unit_class

func reset_to_base_stats():
	max_health = base_max_health
	attack_damage = base_attack_damage
	attack_speed = base_attack_speed
	movement_speed = base_movement_speed
	bonus_armor = 0.0
	bonus_attack_damage = 0.0
	bonus_attack_speed = 0.0
	bonus_ability_power = 0.0
	crit_chance = 0.0

func add_armor(value: float):
	bonus_armor += value

func add_attack_damage(value: float):
	bonus_attack_damage += value

func add_attack_speed(value: float):
	bonus_attack_speed += value

func add_ability_power(value: float):
	bonus_ability_power += value

func add_crit_chance(value: float):
	crit_chance += value

func get_health_percentage() -> float:
	return current_health / max_health

func heal(amount: float):
	current_health = min(current_health + amount, max_health)
	emit_signal("health_changed", current_health, max_health)
	
	# Spawn heal number
	var vfx_manager = get_node_or_null("/root/Main/VFXManager")
	if vfx_manager:
		vfx_manager.spawn_damage_number(global_position, amount, false, true)

func apply_stun(duration: float):
	is_stunned = true
	stun_duration = duration

func create_timer(duration: float):
	await get_tree().create_timer(duration).timeout

func get_mana() -> Dictionary:
	return {
		"current": current_mana,
		"max": max_mana
	}